package com.supreme.cacheserver.service;

import com.supreme.commonentity.mysql.primary.MBTest;
import com.supreme.commonmybatis.mapper.TestMapper;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StopWatch;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.TimeUnit;

@Service
public class BatchTestService {

    @Resource
    private TestMapper testMapper;

    @Resource
    private SqlSessionFactory sqlSessionFactory;

    public int batchInsertLoopInsert(int insertCount) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        int result = 0;
        for (int i = 0; i < insertCount; i++) {
            MBTest test = new MBTest();
            test.setFirstName("firstName" + i);
            test.setLastName("lastName" + i);
            result += testMapper.insert(test);
        }

        stopWatch.stop();
        double totalTimeSeconds = stopWatch.getTotalTimeSeconds();
        System.out.println("totalTimeSeconds = " + totalTimeSeconds);
        return result;
    }

    public int batchInsertFromForEach(int insertCount) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();

        List<MBTest> testList = new ArrayList<>();
        for (int i = 0; i < insertCount; i++) {
            MBTest test = new MBTest();
            test.setFirstName("firstName" + i);
            test.setLastName("lastName" + i);
            testList.add(test);
        }
        int result = testMapper.batchInsertTest(testList);

        stopWatch.stop();
        double totalTimeSeconds = stopWatch.getTotalTimeSeconds();
        System.out.println("totalTimeSeconds = " + totalTimeSeconds);
        return result;
    }

    public int batchInsertFromSqlSession(int insertCount) {
        StopWatch stopWatch = new StopWatch();
        SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
        TestMapper sessionMapper = sqlSession.getMapper(TestMapper.class);
        try {
            stopWatch.start();
            for (int i = 0; i < insertCount; i++) {
                MBTest test = new MBTest();
                test.setFirstName("firstName" + i);
                test.setLastName("lastName" + i);
                sessionMapper.insert(test);
            }
            sqlSession.commit();
            sqlSession.clearCache();
        } catch (Exception e) {
            sqlSession.rollback();
        } finally {
            sqlSession.close();

            stopWatch.stop();
            double totalTimeSeconds = stopWatch.getTotalTimeSeconds();
            System.out.println("totalTimeSeconds = " + totalTimeSeconds);
        }

        return 0;
    }

    @Transactional(rollbackFor = Exception.class)
    public void insertTestForTransaction(Long duration) {
        Thread thread = Thread.currentThread();
        System.out.println("thread.getName() = " + thread.getName());

        try {
            TimeUnit.SECONDS.sleep(duration);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        String firstName = RandomStringUtils.randomAlphabetic(16);
        String lastName = RandomStringUtils.randomAlphabetic(16);
        MBTest test = new MBTest();
        test.setFirstName(firstName);
        test.setLastName(lastName);
        testMapper.insert(test);
    }
}
